package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"os"
)

func main() {
	GenerateRsaKey(4096)
	src := []byte("hello，这里是中央情报局")
	cipherText := RSAEncrypt(src,"public.pem")
	plainText := RSADecrypt(cipherText,"private.pem")
	fmt.Println(string(plainText))
}

// 生成 rsa 密钥对
func GenerateRsaKey(keySize int) {
	/***************** 私钥 **********************/
	// 1 生产私钥
	privateKey,err := rsa.GenerateKey(rand.Reader, keySize)
	if err != nil {
		panic(err)
	}
	//fmt.Printf("%X",*privateKey)

	// 2 通过x509标准PKCS1格式将得到的rsa私钥序列化为ASN.1的DER编码字符串
	derText := x509.MarshalPKCS1PrivateKey(privateKey)

	// 3 将私钥字符串设置到pem格式块中，组织一个pem.Block
	block := pem.Block{
		Type : "rsa private key",
		Bytes: derText,
	}

	// 4 pem编码
	file,err := os.Create("private.pem")	// 创建文件
	if err != nil {
		panic(err)
	}
	pem.Encode(file,&block)
	file.Close()

	/***************** 公钥**********************/
	// 1 从私钥结构体中取出公钥
	publicKey := privateKey.PublicKey

	// 2 使用x509标准序列化
	derpText,err := x509.MarshalPKIXPublicKey(&publicKey)
	if err != nil {
		panic(err)
	}

	// 3 组织一个pem.Block
	block = pem.Block{
		Type:"rsa public key",
		Bytes:derpText,
	}

	// 4 pem编码
	file,err = os.Create("public.pem")
	if err != nil {
		panic(err)
	}
	pem.Encode(file,&block)
	file.Close()
}

/**
 * RSA公钥加密
 * @param plainText 需要加密的明文
 * @param fileName  公钥文件名
 */
func RSAEncrypt(plainText []byte,fileName string) []byte {
	// 1 打开公钥文件，读取文件的内容
	file,err := os.Open(fileName)
	if err != nil {
		panic(err)
	}
	fileInfo,err := file.Stat()
	if err != nil {
		panic(err)
	}
	buf := make([]byte,fileInfo.Size())
	file.Read(buf)	// 读取公钥文件内容
	file.Close()

	// 2 pem解码
	block,_ := pem.Decode(buf)	 // 解码

	// 3 x509解析得到公钥
	pubInterface,err := x509.ParsePKIXPublicKey(block.Bytes)
	// 断言类型转换
	pubKey := pubInterface.(*rsa.PublicKey)

	// 4 使用公钥加密
	cipherText,err := rsa.EncryptPKCS1v15(rand.Reader,pubKey,plainText)
	if err != nil {
		panic(err)
	}
	return cipherText
}

// RSA 私钥解密
// cipherText 公钥加密过的秘闻
// fileName   私钥文件名
func RSADecrypt(cipherText []byte,fileName string) []byte {
	// 1 打开文件，读出私钥文件内容
	file,err := os.Open(fileName)
	if err != nil {
		panic(err)
	}
	fileInfo,err := file.Stat()
	buf := make([]byte,fileInfo.Size())
	file.Read(buf)
	file.Close()

	// 2 pem解码
	block,_ := pem.Decode(buf)

	// 3 x509解析得到私钥
	privKey,err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		panic(err)
	}

	// 4 使用私钥解密
	plainText,err := rsa.DecryptPKCS1v15(rand.Reader,privKey,cipherText)
	if err != nil {
		panic(err)
	}
	return plainText
}

































